<?php
/**
 * 全局方法声明
 */

use App\Events\UserCourseChangeEvent;
use App\Events\UserLearnVideoChangeEvent;
use App\Models\BaseModel;
use App\Models\Coupon;
use App\Models\CourseColumn;
use App\Models\Document;
use App\Models\Knowledge;
use App\Models\LearnVideo;
use App\Models\LearnVideoSection;
use App\Models\Qh_Banner;
use App\Models\Qh_Course;
use App\Models\Qh_Knowledge;
use App\Models\Qh_QuestionLibrary;
use App\Service\Redis\RedisBaseService;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\HigherOrderBuilderProxy;
use Illuminate\Support\Facades\DB;
use LaravelIdea\Helper\App\Models\_IH_BaseModel_C;
use LaravelIdea\Helper\App\Models\_IH_Qh_Banner_C;

/**
 * 将字符串中静态资源相对路径替换为阿里云oss绝对路径
 * @param $str
 * @param string $needle
 * @param string $replace
 * @return array|string|string[]
 */
function replaceStaticFileUrlInString($str, string $needle = '/tikuimg/', $replace = '/tikuimg/')
{
    if (mb_stristr($str, 'https://') || mb_stristr($str, 'https://')) return $str;
    return str_replace($needle, config('filesystems.disks.ftp.domain') . $replace, $str);
}

if (!function_exists('array_get')) {

    /**
     * Get an item from an array using "dot" notation.
     *
     * @param ArrayAccess|array $array
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    function array_get($array, string $key, $default = null)
    {
        return Arr::get($array, $key, $default);
    }
}


/**
 * 建立文件夹
 *
 * @param string $aimUrl
 * @return bool
 */
function createDir(string $aimUrl): bool
{
    $aimUrl = str_replace('', '/', $aimUrl);
    $aimDir = '';
    $arr = explode('/', $aimUrl);
    $result = true;
    foreach ($arr as $str) {
        $aimDir .= $str . '/';
        if (!file_exists($aimDir)) {
            $result = mkdir($aimDir);
        }
    }
    return $result;
}


if (!function_exists('isSelectTitle')) {
    //判断Str是否是选择题选择项
    function isSelectTitle($str): bool
    {
        $pattern = "/^([a-zA-Z]+(．).*)/i";
        return !(preg_match($pattern, $str) == 0);
    }
}

if (!function_exists('isBigTitle')) {
//判断Str是否是大标题
    function isBigTitle($str): bool
    {
        $start_str = mb_substr($str, 0, 2);
        if (in_array($start_str, array('一、', '二、', '三、', '四、', '五、', '六、', '七、', '八、'))) {
            return true;
        } else {
            return false;
        }
    }
}

if (!function_exists('isTitle')) {
//判断Str是否存在小标题号
    function isTitle($str): bool
    {
        $pattern = "/^(\d)+(．).*/i";
        return !(preg_match($pattern, $str) == 0);
    }
}

/**
 * word导入后替换字符串中换行符
 * @param $str
 * @return array|string|string[]
 */
function wordImportBrFormat($str)
{
    return str_replace('[BR]', '<br/>', $str);
}

function isParentQuestion($str)
{

}

/**
 * mathMl 转 Latex
 * @param $input
 * @param string $type
 * @return array|mixed|string|string[]
 */
function mathMl2latex($input, $type = 'toLatex')
{
    $regex = '/<math[^>]*>(.*?)<\/math>/s';  // 匹配以 <math> 开头，以 </math> 结尾的字符串

    $matches = [];

    $formatted = $input;

    if (preg_match_all($regex, $input, $matches)) {
        foreach ($matches[0] as $match) {
            //dump('匹配到的字符串为：' . $match);
            $latex = mml2server($match, $type);
            if (!empty($latex)) {
                if ($type == 'toLatex')
                    $formatted = str_replace($match, '$$' . $latex . '$$', $formatted);
                else
                    $formatted = $latex;
            } else {
                return $input;
            }
        }
    }

    return $formatted;
}

/**
 * mml转latex或png
 * @param $mml
 * @param string $type toLatex|toPng
 * @return mixed|string
 */
function mml2server($mml, string $type = 'toLatex')
{
    $apiUrl = config('services.latex.domain') . '/' . $type;
    // 发送请求转换
    $response = \Illuminate\Support\Facades\Http::post($apiUrl, [
        'math' => $mml
    ]);

    $latex = '';
    if ($response->ok()) {
        $data = $response->json();
        if ($data['success']) {
            $latex = $data['data'];
        }
    }

    return $latex;
}

/**
 * 匹配latex
 * @param $input
 * @param string $imgPath
 * @return array|mixed|string|string[]
 */
function latexMatch($input, string $imgPath = '')
{
    $formatted = $input;

    if (preg_match_all('/\$[^$]*\$/m', $formatted, $matches1)) {
        foreach ($matches1[0] as $match) {
            //dump('匹配到行内公式Latex：' . $match);
            $matched = str_replace('<br>', '', $match);
            $img = latex2png($matched, 'inline-TeX', $imgPath);
            if (!empty($img)) {
                $formatted = str_replace($match, $img, $formatted);;
            }
        }
    }

    if (preg_match_all('/\\\\\\[[^]]*?(?:\\\\]|(?=\\\\\\[))/ms', $formatted, $matches2)) {
        foreach ($matches2[0] as $match) {
            //dump('匹配到行间公式Latex：' . $match);
            $matched = str_replace('<br>', '', $match);
            $img = latex2png($matched, 'TeX', $imgPath);
            if (!empty($img)) {
                $formatted = str_replace($match, $img, $formatted);;
            }
        }
    }

    return $formatted;
}

/**
 * latex代码转图片（url path）
 * @param string $latex
 * @param $format
 * @param string $imgPath
 * @return string
 */
function latex2png(string $latex, $format, string $imgPath = ''): string
{
    $img = $latex;

    $apiUrl = config('services.latex.domain') . '/latex2png';
    // 发送请求转换
    $response = \Illuminate\Support\Facades\Http::post($apiUrl, [
        'math' => $latex,
        'format' => $format,
        'path' => $imgPath
    ]);

    if ($response->ok()) {
        $data = $response->json();
        if ($data['success']) {
            $img = '<img src="' . $data['data'] . '" />';
        }
    }

    return $img;
}

/**
 * 导入：获取三维知识点id
 * @param $question
 * @param $courseId
 * @return array
 */
function importKnowledgeHandle($question, $courseId): array
{
    $knowledge1Id = null;
    $knowledge2Id = null;

    // 知识点
    $knowledge = Knowledge::where('knowledgeName', $question['knowledge'])
        ->where('level', 3)
        ->where('courseId', $courseId)
        ->first();
    if ($knowledge) {
        $knowledge3Id = $knowledge->id;
        $knowledge2 = Knowledge::where('id', $knowledge->parentId)->first();
        if ($knowledge2) {
            $knowledge2Id = $knowledge2->id;
            $knowledge1 = Knowledge::where('id', $knowledge2->parentId)->first();
            if ($knowledge1) $knowledge1Id = $knowledge1->id;
        }
    } else {
        // 创建三级知识点
        $knowledge3Id = DB::table('tiku_knowledge')->insertGetId([
            'courseId' => $courseId,
            'parentId' => null,
            'level' => 3,
            'knowledgeName' => $question['knowledge'],
            'cname' => $question['knowledge'],
            'sortNo' => 0,
            'status' => 0,
            'qCount' => 0,
            'childCount' => 0
        ]);
    }

    return [$knowledge1Id, $knowledge2Id, $knowledge3Id];
}

/**
 * 导入：获取三维知识点id
 * @param $question
 * @param $courseId
 * @param $qlId
 * @return HigherOrderBuilderProxy|int|mixed
 */
function importKnowledgeHandleByQiHang($question, $courseId, $qlId)
{
    // 知识点
    $knowledge = Qh_Knowledge::where('name', $question['knowledge'])
        ->where('level', 2)
        ->where('courseId', $courseId)
        ->first();
    if ($knowledge) {
        $knowledgeId = $knowledge->id;
    } else {
        // 创建二级知识点
        $knowledgeId = DB::table('qh_knowledge')->insertGetId([
            'qlId' => $qlId,
            'courseId' => $courseId,
            'parentId' => null,
            'level' => 2,
            'name' => $question['knowledge'],
            'sort' => 0,
        ]);
    }

    return $knowledgeId;
}

/**
 * 导入：获取题型
 * @param $question
 * @param $courseId
 * @return int|mixed
 */
function importQuestionTypeHandle($question, $courseId)
{
    // 有小题的
    if (!empty($question['children']) && empty($question['questionType'])) {
        $question['questionType'] = '大题';
    }

    if (empty($question['questionType'])) return 0;
    $questionTypeName = trim($question['questionType']);
    $questionType = DB::table('tiku_question_type')
        ->where('courseId', $courseId)
        ->where('questionTypeName', $questionTypeName)
        ->first();
    if (!$questionType) {
        // 创建题型
        $allQuestionTypeFlag = DB::table('tiku_question_type')->groupBy('questionTypeFlag')->pluck('questionTypeFlag')->toArray();
        ksort($allQuestionTypeFlag);
        $newQuestionTypeFlag = $allQuestionTypeFlag[count($allQuestionTypeFlag) - 1] + 1;
        $questionTypeId = DB::table('tiku_question_type')->insertGetId([
            'courseId' => $courseId,
            'questionTypeName' => $questionTypeName,
            'questionTypeFlag' => $newQuestionTypeFlag,
            'sortNo' => 0,
            'status' => 0
        ]);
    } else {
        $questionTypeId = $questionType->id;
    }

    return $questionTypeId;
}

/**
 * 导入：获取题型
 * @param $question
 * @return int|mixed
 */
function importQuestionTypeHandleByQiHang($question)
{
    // 有小题的
    if (!empty($question['children']) && empty($question['questionType'])) {
        $question['questionType'] = '大题';
    }

    if (empty($question['questionType'])) return 0;
    $questionTypeName = trim($question['questionType']);
    $questionType = DB::table('qh_question_types')
        ->where('name', $questionTypeName)
        ->first();
    if (!$questionType) {
        // 创建题型
        $questionTypeId = DB::table('qh_question_types')->insertGetId([
            'name' => $questionTypeName,
            'sort' => 0
        ]);
    } else {
        $questionTypeId = $questionType->id;
    }

    return $questionTypeId;
}


/**
 * 导入：题目入库前结构格式化
 * @param $question
 * @param $courseId
 * @param $province
 * @param $city
 * @param $imgPath
 * @param bool $latexToPng
 * @return array
 * @throws Exception
 */
function importQuestionFormat($question, $courseId, $province, $city, $imgPath, bool $latexToPng = false): array
{
    // 处理题型
    $questionTypeId = importQuestionTypeHandle($question, $courseId);

    // 处理知识点
    $knowledgeIds = importKnowledgeHandle($question, $courseId);

    // 处理公式（可选是否处理）
    try {
        if ($latexToPng) {
            $question = latexToPngInQuestion($question, $imgPath);
        }
    } catch (Exception $e) {
        Log::error('[公式转换服务失败]' . $e->getMessage());
        throw new Exception('公式转换服务失败');
    }

    return [
        'uid' => 550,   // 导入者
        'courseId' => $courseId,
        'questionTypeId' => $questionTypeId,
        'difficulty' => $question['difficulty'],
        'difficultyValue' => $question['difficultyValue'],
        'firstKnowledgeId' => $knowledgeIds[0],
        'secondKnowledgeId' => $knowledgeIds[1],
        'thirdKnowledgeId' => $knowledgeIds[2],
        'create_time' => time(),
        'bodyhtml' => $question['title'],
        'optionCount' => count(array_filter(explode('|NTK|', $question['options']))),  // 选项个数
        'optionHtmlList' => $question['options'],
        //'answer' => in_array($questionTypeId, TK_QUESTION_TYPE_FOR_XZ) ? $question['answer'] : null,  // 只入库选择类题型
        'answer' => $question['answer'],
        'answerHtml' => $question['analysis'],  // 解析
        'anylysis' => null,
        'anylysisHtml' => $question['anylysis'],
        'questionFrom' => '试卷导入',
        'subQuestionFlag' => !empty($question['children']), // 是否有小题
        'area' => $province . ' ' . $city,    // 地区
        'rightCount' => 0,
        'wrongCount' => 0
    ];
}


/**
 * 导入：题目入库前结构格式化
 * @param $question
 * @param $courseId
 * @param $province
 * @param $city
 * @param $imgPath
 * @param bool $latexToPng
 * @return array
 */
function importQuestionFormatByQiHang($question, $courseId, $province, $city, $imgPath, bool $latexToPng = false): array
{
    // 处理题型
    $questionTypeId = importQuestionTypeHandleByQiHang($question);

    $qlId = Qh_Course::find($courseId)->value('qlId');

    // 处理知识点
    $knowledgeId = importKnowledgeHandleByQiHang($question, $courseId, $qlId);

    // 处理公式（可选是否处理）
    if ($latexToPng) {
        $question = latexToPngInQuestion($question, $imgPath);
    }

    return [
        'qlId' => $qlId,
        'courseId' => $courseId,
        'knowledgeId' => $knowledgeId,
        'questionTypeId' => $questionTypeId,
        'title' => $question['title'],
        'optionCount' => count(array_filter(explode('|NTK|', $question['options']))),  // 选项个数
        'options' => $question['options'],
        'answer' => $question['answer'],
        'analysis' => $question['anylysis'],
        'area' => $province . ' ' . $city,    // 地区
        'questionFrom' => '试卷导入',
        'difficulty' => $question['difficulty'],
        'difficultyValue' => $question['difficultyValue'],
        'rightCount' => 0,
        'wrongCount' => 0,
        'sort' => 0,
        'created_at' => Carbon::now()
    ];
}

/**
 * 导入：公式处理
 * @param $question
 * @param string $path
 * @return array
 */
function latexToPngInQuestion($question, string $path = ''): array
{
    $question['title'] = latexMatch($question['title'], $path);
    $question['options'] = latexMatch($question['options'], $path);
    $question['answer'] = latexMatch($question['answer'], $path);
    $question['anylysis'] = latexMatch($question['anylysis'], $path);
    $question['analysis'] = latexMatch($question['analysis'], $path);

    return $question;
}

/**
 * 格式化启航小程序组件值
 * @param $component
 * @return BaseModel[]|Qh_Banner|array|_IH_BaseModel_C|_IH_Qh_Banner_C|mixed|null
 * @throws RedisException
 */
function qhMiniProgramComponentDataFormat($component)
{
    $redisBaseService = new RedisBaseService();
    $data = null;

    if ($component->componentName == 'empty') return $component->data ?? 0;

    $componentData = json_decode($component->data, true);

    if (empty($componentData) && $component->componentName != 'user-data-statistics' && $component->componentName != 'user-card1' && $component->componentName != 'net-course-stat') return null;

    switch ($component->componentName) {
        case 'document':
            $data = Document::select([
                'id',
                'title',
                'downloadCount',
                'viewCount',
                'thumb',
                'print',
                'fileFormat',
                'fileSize',
                'amount'
            ])->where('id', $componentData)->first();
            break;
        case 'coupon':
            $data = Coupon::where('is_active', 1)->where('stop_get', '>', now())->where('id', $componentData)->first();
            break;
        case 'swiper':
            $data = Qh_Banner::whereIn('id', $componentData)->orderByRaw("FIELD(id, " . implode(",",$componentData) . ")")->get();
            break;
        case 'big-swiper':
            $data = [
                'height' => $componentData['height'],
                'list' => Qh_Banner::whereIn('id', $componentData['list'])->orderByRaw("FIELD(id, " . implode(",",$componentData['list']) . ")")->get()
            ];
            break;
        case 'course-card':
            $data = Qh_Course::whereIn('id', $componentData)->orderByRaw("FIELD(id, " . implode(",",$componentData) . ")")->get();
            break;
        case 'course-column':
            $data = CourseColumn::whereIn('id', $componentData)->orderByRaw("FIELD(id, " . implode(",",$componentData) . ")")->get();
            break;
        case 'learn-video-card':
            $data = LearnVideo::whereIn('id', $componentData)->where('is_active', 1)->orderByRaw("FIELD(id, " . implode(",",$componentData) . ")")->get();
            break;
        case 'notice':
        case 'big-title':
        case 'text-list':
        case 'grid-nav':
        case 'small-title':
        case 'offiaccount':
        case 'mini-article-card':
            $data = $componentData;
            break;
        case 'user-data-statistics':
            $data = [
                'daysCount' => 0,
                'countdown' => 0,
                'questionCount' => 0,
                'questionCountOfToday' => 0,
            ];
            if (Auth::guard('api')->check()) {
                $user = Auth::guard('api')->user();
                // 坚持天数
                $data['daysCount'] = $user->ksDaysCount ?? 0;
                // 倒计时
                $data['countdown'] = $user->ksCountdown ? Carbon::now()->diffInDays(Carbon::make($user->ksCountdown)) : 0;
                // 刷题数量
                $data['questionCount'] = $redisBaseService->getUserStatisticsData('statistics:userLearnQuestionCount', $user->id);
                $data['questionCountOfToday'] = $redisBaseService->getUserStatisticsData('statistics:userLearnQuestionOfTodayCount', $user->id);
                $data['qusetionRate'] = $redisBaseService->getUserQuestionRate($user->id);
                $data['qusetionRateP'] = round($data['qusetionRate'] * 100);
                $data['qusetionRateOfToday'] = $redisBaseService->getUserQuestionRateOfToday($user->id);
                $data['qusetionRateOfTodayP'] = round($data['qusetionRateOfToday'] * 100);
            }
            break;
        case 'net-course-stat':
            if (Auth::guard('api')->check()) {
                $user = Auth::guard('api')->user();
                $data = [
                    'minuteOfToday' => $user->netCourseLearnOfLastTime ? (Carbon::make($user->netCourseLearnOfLastTime)->isToday() ? $user->netCourseLearnMinuteOfToday : 0) : 0,       // 今日学习分钟数
                    'hourOfAll' => round($user->netCourseLearnMinute / 60),           // 总学习小时数
                    'learnDays' => ($user->netCourseLearnMinute > 0 && round($user->netCourseLearnMinute / 60 / 24) < 1) ? 1 : round($user->netCourseLearnMinute / 60 / 24),           // 学习天数
                    'learnSection' => $user->learnVideoSectionDoneCount,        // 已学小节
                    'allSection' => $user->learnVideoSectionCount,          // 所有小节
                ];
            }else {
                $data = [
                    'minuteOfToday' => 0,       // 今日学习分钟数
                    'hourOfAll' => 0,           // 总学习小时数
                    'learnDays' => 0,           // 学习天数
                    'learnSection' => 0,        // 已学小节
                    'allSection' => 0,          // 所有小节
                ];
            }
            break;
        case 'user-card1':
            $data = [
                'wrongQuestionCount' => 0
            ];
            if (Auth::guard('api')->check()) {
                $user = Auth::guard('api')->user();
                $data['wrongQuestionCount'] = $redisBaseService->getUserStatisticsData('statistics:userWrongQuestionCount', $user->id);
            }
            break;
    }

    return $data;
}


/**
 * 试题数量更新
 * @param $knowledgeId
 * @param $count
 * @param int $mode 模式，1：加，2：减
 * @return void
 */
function updateQhQuestionCount($knowledgeId, $count, int $mode=1) {
    // 知识点试题数量增加
    $knowledge = Qh_Knowledge::find($knowledgeId);
    if ($knowledge) {
        if ($mode == 1) $knowledge->questionCount += $count;
        if ($mode == 2) $knowledge->questionCount -= $count;
        $knowledge->save();
        $knowledge1 = Qh_Knowledge::find($knowledge->parentId);
        if ($knowledge1) {
            if ($mode == 1) $knowledge1->questionCount += $count;
            if ($mode == 2) $knowledge1->questionCount -= $count;
            $knowledge1->save();
        }

        // 题库试题数量增加
        $ql = Qh_QuestionLibrary::find($knowledge->qlId);
        if ($ql) {
            if ($mode == 1) $ql->questionCount += $count;
            if ($mode == 2) $ql->questionCount -= $count;
            $ql->save();
        }

        // 学科试题数量增加
        $course = Qh_Course::find($knowledge->courseId);
        if ($course) {
            if ($mode == 1) $course->questionCount += $count;
            if ($mode == 2) $course->questionCount -= $count;
            $course->save();
        }
    }
}


/**
 * 生成随机字符串
 * @param int $length
 * @return string
 */
function generateRandomString(int $length = 10): string
{
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';

    for ($i = 0; $i < $length; $i++) {
        $index = mt_rand(0, strlen($characters) - 1);
        $randomString .= $characters[$index];
    }

    return $randomString;
}

/**
 * 生成激活码
 * @return false|string
 */
function generateCdkey() {
    $str = generateRandomString();
    $time = time();
    $cdkey = str_shuffle($str.$time);
    return substr($cdkey, 5 ,10);
}

function onlineFileToDiskFile($url): ?string
{
    // 获取图片内容
    $imageContent = file_get_contents($url);

    if ($imageContent !== false) {
        // 生成本地临时文件名
        $tempFilePath = tempnam(sys_get_temp_dir(), 'tempfile_');
        $tempPhpFilePath = $tempFilePath . '.'.pathinfo($url, PATHINFO_EXTENSION);
        // 将远程文件内容保存到本地临时文件
        file_put_contents($tempPhpFilePath, $imageContent);
        return $tempPhpFilePath;
    } else {
        return null;
    }
}

/**
 * 格式化用户错题/收藏所需的数据结构
 * @param $ids
 * @param null $userId
 * @return array
 * @throws RedisException
 */
function formatUserWrongOrCollectQuestion($ids, $userId=null): array
{
    $data = [];
    // 格式化数据
    foreach ($ids as $courseId => $knowledgeIds) {
        $_course = Qh_Course::find(explode(':', $courseId)[1]);

        // if ($userId) {
        //     $userCourseIds = (new RedisBaseService())->getUserHadCourseIds($userId);
        //     $userHas = in_array($_course->id, $userCourseIds);
        // }else {
        //     $userHas = $_course->userHas;
        // }
        // $userHas = $_course->userHas;
        $userHas = true;        // TODO:暂时改为开发

        $_wrongQuestionCount = 0;
        if (!$_course) continue;
        $knowledge = [];
        foreach ($knowledgeIds as $knowledgeId => $kIds) {
            // $_knowledge = Qh_Knowledge::whereNull('parentId')->where('id', explode(':', $knowledgeId)[1])->first();
            $_knowledge = DB::table('qh_knowledge')->select(['id', 'parentId', 'name'])->whereNull('parentId')->where('id', explode(':', $knowledgeId)[1])->first();
            if (!$_knowledge) continue;

            $k = [];
            $_wrongQuestionCountOfK = 0;
            foreach ($kIds as $kId => $qIds) {
                // $_k = Qh_Knowledge::where('parentId', explode(':', $knowledgeId)[1])->where('id', explode(':', $kId)[1])->first();
                $_k = DB::table('qh_knowledge')->select(['id', 'parentId', 'name'])->where('parentId', explode(':', $knowledgeId)[1])->where('id', explode(':', $kId)[1])->first();
                if (!$_k) continue;

                // $_questions = Qh_Question::whereIn('id', $qIds)->get();
                // 节
                $k[] = [
                    'id' => $_k->id,
                    'name' => $_k->name,
                    'questionCount' => count($qIds),
                    'userHas' => $userHas,
                    'progress' => 0,
                    // 'children' => $_questions
                ];
                $_wrongQuestionCountOfK += count($qIds);
                $_wrongQuestionCount += count($qIds);
            }

            // 章
            $knowledge[] = [
                'id' => $_knowledge->id,
                'name' => $_knowledge->name,
                'questionCount' => $_wrongQuestionCountOfK,
                'userHas' => $userHas,
                'progress' => 0,
                'children' => $k
            ];
        }

        // 学科
        $data[] = [
            'id' => $_course->id,
            'name' => $_course->name,
            'questionCount' => $_wrongQuestionCount,
            'userHas' => $userHas,
            'progress' => 0,
            'children' => $knowledge
        ];
    }

    return $data;
}


/**
 * 从错题或收藏题结构数据中获取指定级别的数据
 * @param $data
 * @param $level    1：学科、2：章、3：节、4：题
 * @param $key
 * @return array
 */
function getLevelDataFromWrongOrCollectQuestionStructureData($data, $level, $key): array
{

    if ($level > 1) {
        if ($level > 2) {
            if ($level > 3) {
                // level 4
                foreach ($data as $course) {
                    foreach ($course as $knowledge) {
                        foreach ($knowledge as $questions) {
                            if (in_array($key, $questions)) return [$key];
                        }
                    }
                }
            }else {
                // level 3
                foreach ($data as $course) {
                    foreach ($course as $knowledge) {
                        if (array_key_exists('kId:'.$key, $knowledge)) return $knowledge['kId:'.$key];
                    }
                }
            }

        }else {
            // level 2
            foreach ($data as $course) {
                if (array_key_exists('knowledgeId:'.$key, $course)) return $course['knowledgeId:'.$key];
            }
        }

    }else {
        // level 1
        if (array_key_exists('courseId:'.$key, $data)) return $data['courseId:'.$key];
    }

    return [];

    // foreach ($data as $_courseKey => $course) {
    //     if ($level > 1) {
    //
    //         if ($level > 2) {
    //             // 3
    //
    //         }else {
    //             if (array_key_exists('knowledgeId:'.$key, $course)) return $course;
    //         }
    //
    //         foreach ($course as $_knowledgeKey => $knowledge) {
    //             if ($level > 2) {
    //                 foreach ($knowledge as $questions) {
    //                     dd($k);
    //                 }
    //                 if ($level > 3) {
    //                     foreach ($knowledge as $questions) {
    //                         if (in_array($key, $questions)) return [$key];
    //                     }
    //                 }else {
    //                     if (array_key_exists('kId:'.$key, $knowledge)) return $knowledge['kId:'.$key];
    //                 }
    //             } else {
    //                 if ($_knowledgeKey == 'knowledgeId:'.$key) return $knowledge;
    //             }
    //         }
    //     }else {
    //         if ($_courseKey == 'courseId:'.$key) return $course;
    //     }
    // }

    return [];
}

/**
 * 格式化输出时间
 * @param Carbon $endAt
 * @return string
 */
function parserDateStr(Carbon $endAt): string
{
    $now = Carbon::now();
    $diff = $now->diff($endAt);

    if ($diff->invert) {
        // 如果结束时间在当前时间之前，返回已过期
        return '已过期';
    }

    $days = $diff->days;
    $hours = $diff->h;
    $minutes = $diff->i;
    $seconds = $diff->s;

    if ($days === 0) {
        // 如果距离现在少于24小时
        return sprintf('%02d小时%02d分%02d秒', $hours, $minutes, $seconds);
    } elseif ($days < 30) {
        // 如果距离现在大于24小时但小于30天
        return sprintf('%02d天%02d小时%02d分', $days, $hours, $minutes);
    } else {
        // 如果距离现在大于30天
        $months = floor($days / 30);
        $remainingDays = $days % 30;

        // 总是显示月和剩余的天数
        $output = sprintf('%02d月%02d天', $months, $remainingDays);

        // 如果剩余天数为0，则显示小时、分钟和秒（如果它们不为0）
        if ($remainingDays === 0) {
            $output .= sprintf('%02d小时%02d分%02d秒', $hours, $minutes, $seconds);
        } elseif ($hours > 0) {
            // 如果剩余天数不为0但存在小时数，则只显示小时
            $output .= sprintf('%02d小时', $hours);
        }

        return $output;
    }
}

/**
 * 更新用户视频课程记录data
 * @param array $data
 * @param LearnVideoSection $section
 * @param $duration
 * @return array
 */
function updateUserLearnVideoLogData(array &$data, LearnVideoSection $section, $duration): array
{
    //$st = [
    //    [
    //        'chapterId' => 121,
    //        'sections' => [
    //            [
    //                'sectionId' => 122,
    //                'duration' => 12.22,
    //                'rate' => 4.12,
    //                'firstWatch' => time(),
    //                'lastWatch' => time(),
    //            ]
    //        ]
    //    ]
    //];

    $duration = round($duration, 4);
    $sectionCount = 0;

    $chapterKey = null;
    $sectionKey = null;
    foreach ($data as $ck=>$datum) {
        if ($datum['chapterId'] == $section->learn_video_chapter_id) {
            $chapterKey = $ck;
            foreach ($datum['sections'] as $sk=>$_section) {
                if ($_section['sectionId'] == $section->id) {
                    $sectionKey = $sk;
                }
                $sectionCount += 1;
            }
        }
    }

    try {
        $rate = round($duration / $section->total_second, 2);
    }catch (Exception $e) {
        $rate = 0;
    }
    if ($chapterKey === null) {
        $data[] = [
            'chapterId' => $section->learn_video_chapter_id,
            'sections' => [
                [
                    'sectionId' => $section->id,
                    'duration' => $duration,
                    'rate' => $rate,
                    'firstWatch' => time(),
                    'lastWatch' => time(),
                ]
            ]
        ];
        $sectionCount += 1;
    } else {
        if ($sectionKey === null) {
            $data[$chapterKey]['sections'][] = [
                'sectionId' => $section->id,
                'duration' => $duration,
                'rate' => $rate,
                'firstWatch' => time(),
                'lastWatch' => time(),
            ];
            $sectionCount += 1;
        }else {
            $data[$chapterKey]['sections'][$sectionKey]['duration'] = $duration;
            $data[$chapterKey]['sections'][$sectionKey]['rate'] = $rate;
            $data[$chapterKey]['sections'][$sectionKey]['lastWatch'] = time();
        }
    }

    return [
        'sectionCount' => $sectionCount,
        'data' => $data
    ];
}


/**
 * 格式化输出播放时长
 * @param $second
 * @return false|string
 */
function fromatDuration($second) {
    return gmdate("H:i:s", $second);
}


/**
 * 发放视频课程给用户
 * @param array $learnIds
 * @param $userId
 * @param null $expireAt
 * @param int $type 来源，1：直接购买，2：激活码兑换，3：限免，4：其他，5：专栏激活，6：专栏购买
 * @param null $cdkey
 * @return bool
 * @throws Throwable
 */
function sendLearnVideoToUser(array $learnIds, $userId, $expireAt=null, int $type=1, $cdkey=null): bool
{
    $successIds = [];
    $learnVideos = LearnVideo::whereIn('id', $learnIds)->get();
    $sectionCount = 0;
    $_expireAt = $expireAt;

    DB::beginTransaction();
    try {
        foreach ($learnVideos as $learnVideo) {
            $log = DB::table('user_learn_video_logs')
                ->where('userId', $userId)
                ->where('learnVideoId', $learnVideo->id)
                ->first();
            if (!$expireAt) {
                if ($cdkey) {
                    $expireAt = getResourceEffectiveAt($cdkey) ?? getLearnVideoExpireAt($learnVideo);
                }else {
                    $expireAt = getLearnVideoExpireAt($learnVideo);
                }
            }
            if (!$log) {
                $sectionCount += $learnVideo->section_count;
                DB::table('user_learn_video_logs')->insert([
                    'userId' => $userId,
                    'learnVideoId' => $learnVideo->id,
                    'getAt' => now(),
                    'isTry' => 0,
                    'getType' => $type,
                    'expireAt' => $expireAt
                ]);
                event(new UserLearnVideoChangeEvent($userId));
                $learnVideo->real_learn_count += 1;
                $learnVideo->learn_count += 1;
                $learnVideo->save();
            }else {
                if ($log->expireAt) {
                    if ($cdkey) $effectiveModel = $cdkey;
                    else $effectiveModel = $learnVideo;
                    if (Carbon::make($log->expireAt)->gt(now())) {
                        $diffDays = now()->diffInDays($expireAt);
                        $expireAt = Carbon::make($log->expireAt)->addDays($diffDays);
                    }

                    // 天数和小时要单独计算
                    if ($effectiveModel->effective_type == 1) {
                        // 天
                        if (Carbon::make($log->expireAt)->gt(now())) {
                            $expireAt = Carbon::make($log->expireAt)->addDays($effectiveModel->effective_days);
                        }else {
                            $expireAt = now()->addDays($effectiveModel->effective_days);
                        }
                    }
                    elseif ($effectiveModel->effective_type == 2) {
                        // 小时
                        if (Carbon::make($log->expireAt)->gt(now())) {
                            $expireAt = Carbon::make($log->expireAt)->addHours($effectiveModel->effective_hours);
                        }else {
                            $expireAt = now()->addHours($effectiveModel->effective_hours);
                        }
                    }
                }
                DB::table('user_learn_video_logs')
                    ->where('userId', $userId)
                    ->where('learnVideoId', $learnVideo->id)
                    ->update([
                        'getType' => $type,
                        'isTry' => 0,
                        'expireAt' => $expireAt
                    ]);
                event(new UserLearnVideoChangeEvent($userId));
            }
            $successIds[] = $learnVideo->id;
            $expireAt = $_expireAt;
        }
        // 更新用户拥有的课程数量
        DB::table('user')->where('id', $userId)->increment('learnVideoSectionCount', $sectionCount);
    }catch (Exception $e) {
        Log::error($e);
        $successIds = [];
        DB::rollBack();
        return false;
    }
    DB::commit();
    return true;
}

/**
 * 发放题库/学科给用户
 * @param array $courseIds  学科IDS
 * @param $userId   用户ID
 * @param $orderId  订单ID
 * @param $type 来源，1：直接购买，2：激活码兑换
 * @return bool
 * @throws Throwable
 */
function sendCourseToUser(array $courseIds, $userId, $orderId=null, $type=1)
{
    $successIds = [];

    DB::beginTransaction();

    try {
        foreach ($courseIds as $courseId) {
            // 将学科添加到用户
            $result = DB::table('qh_user_has_course')->updateOrInsert([
                'userId' => $userId,
                'courseId' => $courseId,
            ], [
                'sourceId' => $orderId,
                'type' => $type,
                'created_at' => Carbon::now()
            ]);
            $successIds[] = $courseId;
        }
    }catch (Exception $e) {
        Log::error($e);
        $successIds = [];
        DB::rollBack();
        return false;
    }
    DB::commit();

    // 更新用户拥有的学科缓存
    UserCourseChangeEvent::dispatch($userId);

    return true;
}


/**
 * 发放文档给用户
 * @param array $documentIds
 * @param $userId
 * @param $orderId
 * @param $type 获得类型：1=购买,2=激活,3=发放
 * @return bool
 * @throws Throwable
 */
function sendDocumentToUser(array $documentIds, $userId, $orderId=null, $type=1)
{
    $successIds = [];

    DB::beginTransaction();

    try {
        foreach ($documentIds as $documentId) {
            // 将文档添加到用户
            $result = DB::table('qh_user_has_document')->updateOrInsert([
                'userId' => $userId,
                'documentId' => $documentId,
            ], [
                'orderId' => $orderId,
                'type' => $type,
                'created_at' => now()
            ]);
        }
        $successIds[] = $documentId;
    }catch (Exception $e) {
        Log::error($e);
        $successIds = [];
        DB::rollBack();
        return false;
    }

    DB::commit();
    return true;
}

/**
 * 移除已解锁的专栏资源
 * @param $userId
 * @param $courseColumn
 * @return void
 */
function unlockCourseColumnResource($userId, $courseColumn)
{
    // 获取专栏中的资源
    $resource = $courseColumn->resource;

    if (!empty($resource['courses'])) {
        $courseIds = $resource['courses'] ?? [];
        DB::table('qh_user_has_course')
            ->where('userId', $userId)
            ->whereIn('courseId', $courseIds)
            ->delete();

        // 更新用户拥有的学科缓存
        UserCourseChangeEvent::dispatch($userId);
    }
    if (!empty($resource['documents'])) {
        $documentIds = $resource['documents'] ?? [];
        DB::table('qh_user_has_document')
            ->where('userId', $userId)
            ->whereIn('documentId', $documentIds)
            ->delete();
    }
    if (!empty($resource['learn_videos'])) {
        $learnVideoIds = $resource['learn_videos'] ?? [];
        foreach ($learnVideoIds as $learnVideoId) {
            unlockLearnVideo($userId, $learnVideoId);
        }
    }
    DB::table('user_course_column_buy_logs')->where('userId', $userId)->where('dataId', $courseColumn->id)->delete();
}

/**
 * 移除已激活的视频单科
 * @param $userId
 * @param $activeDataId
 * @return void
 */
function unlockLearnVideo($userId, $activeDataId)
{
    DB::table('user_learn_video_logs')
        ->where('userId', $userId)
        ->where('learnVideoId', $activeDataId)
        ->update([
            'expireAt' => now()
        ]);
    event(new UserLearnVideoChangeEvent($userId));

    $learnVideoSectionCount = DB::table('learn_videos')->where('id', $activeDataId)->value('section_count') ?? 0;
    // 更新用户拥有的课程数量
    $userLearnVideoSectionCount = DB::table('user')->where('id', $userId)->value('learnVideoSectionCount') ?? 0;
    $userLearnVideoSectionCount = $userLearnVideoSectionCount >= $learnVideoSectionCount ? $userLearnVideoSectionCount - $learnVideoSectionCount : 0;
    DB::table('user')->where('id', $userId)->update(['learnVideoSectionCount' => $userLearnVideoSectionCount]);
}

/**
 * 计算专栏过期时间
 * @param CourseColumn $courseColumn
 * @return Carbon|\Illuminate\Support\Carbon|null
 */
function getCourseColumnExpireAt(CourseColumn $courseColumn)
{
    // 计算日期
    $expireAt = now();
    if ($courseColumn->effective_type == 1) {
        // 天
        $expireAt->addDays($courseColumn->effective_days ?? 1);
    }
    if ($courseColumn->effective_type == 2) {
        // 小时
        $expireAt = now()->addHours($courseColumn->effective_hours ?? 1);
    }
    elseif ($courseColumn->effective_type == 3) {
        // 日期
        $expireAt = Carbon::make($courseColumn->effective_date ?? now()->addDays(1));
    }
    elseif ($courseColumn->effective_type == 4) {
        // 长期
        $expireAt->addYears(100);
    }
    return $expireAt;
}

/**
 * 获取单科过期时间
 * @param LearnVideo $learnVideo
 * @return Carbon|\Illuminate\Support\Carbon|null
 */
function getLearnVideoExpireAt(LearnVideo $learnVideo)
{
    // 计算日期
    $expireAt = now();
    if ($learnVideo->effective_type == 1) {
        // 天
        $expireAt->addDays($learnVideo->effective_days ?? 1);
    }
    if ($learnVideo->effective_type == 2) {
        // 小时
        $expireAt = now()->addHours($learnVideo->effective_hours ?? 1);
    }
    elseif ($learnVideo->effective_type == 3) {
        // 日期
        $expireAt = Carbon::make($learnVideo->effective_date ?? now()->addDays(1));
    }
    elseif ($learnVideo->effective_type == 4) {
        // 长期
        $expireAt->addYears(100);
    }
    return $expireAt;
}

function getResourceEffectiveAt($model)
{
    // 计算日期
    if (!$model->effective_type) return null;
    $expireAt = null;
    if ($model->effective_type == 1) {
        // 天
        $expireAt = now()->addDays($model->effective_days ?? 1);
    }
    if ($model->effective_type == 2) {
        // 小时
        $expireAt = now()->addHours($model->effective_hours ?? 1);
    }
    elseif ($model->effective_type == 3) {
        // 日期
        $expireAt = $model->effective_date ? Carbon::make($model->effective_date) : now()->addDays();
    }
    elseif ($model->effective_type == 4) {
        // 长期
        $expireAt = now()->addYears(100);
    }
    return $expireAt;
}
